package biz

import (
	"context"
	"fmt"
	pb "go_private_im/api/comet"
	"go_private_im/api/protocol"
	"time"
)


type PushMsg struct {
	Keys    []string
	ProtoOp int32
	Proto   *protocol.Proto
}

func (c *CometUsecase) PushMsg (ctx context.Context,pushMsg *PushMsg) (err error)  {
	for _, key := range pushMsg.Keys {
		fmt.Println(key, "2222222222222", c.Bucket(key))
		if channel := c.Bucket(key).Channel(key); channel != nil {
			fmt.Println(channel, "channeldddddddddddd")
			if !channel.NeedPush(pushMsg.ProtoOp) {
				continue
			}
			if err = channel.Push(pushMsg.Proto); err != nil {
				return
			}
		}
	}
	return
}

type BroadcastMsg struct {
	ProtoOp int32
	Proto   *protocol.Proto
	Speed   int32
}

func (c *CometUsecase) Broadcast(ctx context.Context,broadcastMsg *BroadcastMsg) (err error) {
	// TODO use broadcast queue
	go func() {
		for _, bucket := range c.Buckets() {
			bucket.Broadcast(broadcastMsg.Proto, broadcastMsg.ProtoOp)
			if broadcastMsg.Speed > 0 {
				t := bucket.ChannelCount() / int(broadcastMsg.Speed)
				time.Sleep(time.Duration(t) * time.Second)
			}
		}
	}()
	return
}


func (c *CometUsecase) BroadcastRoom(ctx context.Context,broadcastRoom *pb.BroadcastRoomReq) (err error) {
	for _, bucket := range c.Buckets() {
		bucket.BroadcastRoom(broadcastRoom)
	}
	return
}

type RoomsReply struct {
	Rooms    map[string]bool
}
func (c *CometUsecase) Rooms(ctx context.Context) *RoomsReply {
	var (
		roomIds = make(map[string]bool)
	)
	for _, bucket := range c.Buckets() {
		for roomId := range bucket.Rooms() {
			roomIds[roomId] = true
		}
	}
	return &RoomsReply{
		Rooms: roomIds,
	}
}

type AddRoom struct {
	Keys []string

	RoomId string

	Op int32
}

func (c *CometUsecase) UserAddRoom (ctx context.Context, addRoom *AddRoom) (err error) {
	for _, key := range addRoom.Keys {
		if channel := c.Bucket(key).Channel(key); channel != nil {
			fmt.Println(channel, "UserAddRoom")
			if !channel.NeedPush(addRoom.Op) {
				channel.OneWatch(addRoom.Op)
				b := c.Bucket(key)
				err = b.RoomPutChannel(addRoom.RoomId,channel)
			}
		}
	}
	return
}

type OutRoom struct {
	Keys []string

	RoomId string

	Op int32
}

func (c *CometUsecase) UserOutRoom (ctx context.Context, outRoom *OutRoom) (err error) {
	for _, key := range outRoom.Keys {
		if channel := c.Bucket(key).Channel(key); channel != nil {
			fmt.Println(channel, "UserAddRoom")
			if channel.NeedPush(outRoom.Op) {
				channel.UnWatch(outRoom.Op)
				b := c.Bucket(key)
				b.Del(channel)
			}
		}
	}
	return
}
